using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using Platform.Buff;
using Platform.Buff.Buffs;
using UnityEngine;
using Plugin.Tool;
using Pixelplacement;
using System.IO;
using cfg.item;
using SimpleJSON;
using cfg;

namespace Platform.CharacterData
{
    public class CharacterStats : MonoBehaviour
    {
        [Header("角色类型")]
        //follow 此处绑定对应SO数据
        public int id;
        // public CharacterType characterType;
        //配置的数据是数值，不能直接用   可以在打包阶段取消反射
        // public CharacterDataDetails characterData;

        #region 基础属性
        [Header("角色基本属性")]
        [HideInInspector] public string skillDataName;
        public SkillDataSO skillDataList;
        [HideInInspector] public string animalName;
        public RuntimeAnimatorController animController;

        [Header("阵营")]
        public Faction faction;

        [Header("种族")]
        public Race race;

        [Header("描述")]
        public string description;
        public Sprite menuSprite;

        [Header("基础属性")]
        public Stat jumpHeight;
        public Stat moveSpeed;
        #endregion

        #region 主属性

        [Header("主属性")]
        public Stat strength; //1 伤害 1% 暴击力量
        public Stat agility; // 1 闪避 1% 暴击
        public Stat intelligence; // 1 魔法伤害 3% 法抗
        public Stat vitality; // 5hp

        [Header("防御属性")]
        public Stat maxHealth;
        public int MaxHealth => (int)(maxHealth.Value + vitality.Value);
        public Stat armor;

        /// <summary>
        /// 防御倍率   背后减半
        /// </summary>
        public Stat backArmorMultiplier; //调整倍率
        public Stat magicResistance;
        public Stat evasion; //闪避

        [Header("抗性")]
        /// <summary>
        /// 击退抗性
        /// </summary>   
        public Stat knockbackResistance;

        [Header("攻击属性")]
        public Stat damage;
        public Stat critChangce;
        public Stat critPower;

        [Header("魔法攻击属性")]
        public Stat fireDamage;
        public Stat iceDamage;
        public Stat electricDamage;
        public Stat toxicDamage;

        #region 其他属性
        /// <summary>
        /// 轻攻击和重攻击分别设置
        /// </summary>
        [Header("攻击伤害类型")]
        public AttackDamageType lightAttackDamageType;
        public AttackDamageType heavyAttackDamageType;
        [Header("攻击位移")]
        public List<Vector2> lightDoubleAttackMovement;
        public List<Vector2> heavyDoubleAttackMovement;

        [Header("武器击退力")]
        public Stat knockBackPower;
        public Vector2 knockBackForce;

        // [Header("攻击状态对应的碰撞盒")]
        // public Dictionary<Entity.States, AttackRanges> attackRangeDict = new();

        // [Header("combo配置")]
        // public int lightDoubleAttackComboMax;
        // public int heavyDoubleAttackComboMax;

        #endregion

        [Header("击晕/硬直")]
        public Stat stunDuration;
        public Vector2 stunDirection;
        public GameObject counterImg;

        // [Header("打击特效")] 目前自动生成
        // public HitEffect lightHitEffect;
        // public HitEffect heavyHitEffect;

        #region 打击感
        [Header("打击帧数")]
        public float lightFreaze;
        public float heavyFreaze;
        public Vector2 lightPower;
        public Vector2 heavyPower;
        #endregion
        #endregion

        #region 动态属性
        public bool beCrit;
        [Header("buff")]
        public List<BuffBase> buffs = new List<BuffBase>();

        [SerializeField]
        private int _currentHealth;
        public int CurrentHealth
        {
            get { return _currentHealth; }
            set
            {
                OnHealthChange?.Invoke();
                _currentHealth = value;
            }
        }

        [HideInInspector] public EntityFX fx;
        [HideInInspector] public Entity entity;

        [HideInInspector] public HitEffect currentHitEffect;
        [HideInInspector] public AttackDamageType currentAttackDamageType;

        private bool isBackAttack = false;
        #endregion

        #region  事件
        public Action OnHealthChange;
        #endregion

        #region 生命周期

        void FixedUpdate()
        {
            ReFreshBuff();
        }

        protected virtual void Awake()
        {
            entity = GetComponent<Entity>();
            fx = GetComponent<EntityFX>();

            // SOMgr.Instance.OnSODataLoaded += SetStats;
            SetStats();
        }
        void OnDestroy()
        {
            // SOMgr.Instance.OnSODataLoaded -= SetStats;
        }
        void SetStats()
        {
            // characterData = SOMgr.Instance.GetCharacterDataDetails(characterType);
            InitDataFromTable();
            CurrentHealth = MaxHealth;
            if (skillDataName.NotNullOrEmpty()) skillDataList = AAMgr.LoadAsset<SkillDataSO>(skillDataName);
            if (animalName.NotNullOrEmpty()) animController = AAMgr.LoadAsset<RuntimeAnimatorController>(animalName);
        }

        #region so初始化
        //缓存反射信息
        // private static Dictionary<string, FieldInfo> characterDataFields = new Dictionary<string, FieldInfo>();
        // private static Dictionary<string, FieldInfo> statFields = new Dictionary<string, FieldInfo>();
        // static CharacterStats()
        // {
        //     // Cache fields from CharacterDataSO
        //     foreach (var field in typeof(CharacterDataDetails).GetFields())
        //     {
        //         characterDataFields[field.Name] = field;
        //     }

        //     // Cache fields from the current class
        //     foreach (var field in typeof(CharacterStats).GetFields())
        //     {
        //         if (field.FieldType == typeof(Stat))
        //         {
        //             statFields[field.Name] = field;
        //         }
        //     }
        // }
        // public void InitData()
        // {
        //     //特殊处理list
        //     // foreach (var item in characterData.attackRangeList)
        //     // {
        //     //     if (!attackRangeDict.ContainsKey(item.Key))
        //     //     {
        //     //         attackRangeDict.Add(item.Key, item.Value);
        //     //     }
        //     // }

        //     var type = GetType();
        //     foreach (var kvp in characterDataFields)
        //     {
        //         var fieldName = kvp.Key;
        //         var sourceField = kvp.Value;
        //         var targetField = type.GetField(fieldName);

        //         if (targetField != null)
        //         {
        //             if (targetField.FieldType == sourceField.FieldType)
        //             {
        //                 targetField.SetValue(this, sourceField.GetValue(characterData));
        //             }
        //             else if (statFields.TryGetValue(fieldName, out var statField))
        //             {
        //                 var targetStat = (Stat)statField.GetValue(this);
        //                 var valueField = statField.FieldType.GetProperty("Value");

        //                 if (valueField != null)
        //                 {
        //                     valueField.SetValue(targetStat, sourceField.GetValue(characterData));
        //                 }
        //             }
        //         }
        //     }
        // }
        #endregion
        #region  luban
        public void InitDataFromTable()
        {
            string configDir = Application.streamingAssetsPath + "/Luban";
            var tables = new cfg.Tables(file => JSON.Parse(File.ReadAllText($"{configDir}/{file}.json")));

            var table = tables.Tbcharacter.Get(id);
            // 反射遍历当前类的所有公共字段
            FieldInfo[] fields = table.GetType().GetFields();
            var thisType = GetType();
            foreach (var sourceField in fields)
            {
                var fieldName = sourceField.Name;
                if (fieldName == "Id") continue;
                var targetName = LowercaseFirstLetter(fieldName);
                var targetField = thisType.GetField(targetName);
                if (targetField != null)
                {
                    if (targetField.FieldType == sourceField.FieldType)
                    {
                        targetField.SetValue(this, sourceField.GetValue(table));
                    }
                    else if (targetField.FieldType == typeof(Stat))
                    {
                        var targetStat = (Stat)targetField.GetValue(this);
                        var valueField = targetField.FieldType.GetProperty("Value");

                        if (valueField != null)
                        {
                            valueField.SetValue(targetStat, sourceField.GetValue(table));
                        }
                    }
                    else if (sourceField.FieldType == typeof(cfg.vector2) && targetField.FieldType == typeof(Vector2))
                    {
                        var vector2 = (cfg.vector2)sourceField.GetValue(table);
                        targetField.SetValue(this, new Vector2(vector2.X, vector2.Y));
                    }
                    else if (sourceField.FieldType == typeof(List<cfg.vector2>) && targetField.FieldType == typeof(List<Vector2>))
                    {
                        var vector2s = (List<cfg.vector2>)sourceField.GetValue(table);
                        targetField.SetValue(this, vector2s.Select(v => new Vector2(v.X, v.Y)).ToList());
                    }
                    //处理枚举
                    // else if (targetField.FieldType.BaseType == typeof(Enum))
                }
            }

            string LowercaseFirstLetter(string input)
            {
                if (string.IsNullOrEmpty(input))
                {
                    return input;
                }

                char[] charArray = input.ToCharArray();
                charArray[0] = char.ToLower(charArray[0]);
                return new string(charArray);
            }

        }
        #endregion
        #endregion

        #region  伤害处理
        public void TakeDamage(float damage, CharacterStats sourceStats)
        {
            CurrentHealth -= (int)damage;

            if (CurrentHealth <= 0)
                Die();
            else
                entity.OnHit(sourceStats);

            if (damage >= 0)
                fx.CreatePop(((int)damage).ToString());
        }

        /// <summary>
        /// 普通攻击处理
        /// todo 拆分数值处理和特性处理
        /// </summary>
        /// <param name="sourceStats"></param>
        public virtual void BeDamage(CharacterStats sourceStats, Collider2D other = null)
        {
            if (CanAvoidAttack(sourceStats))
            {
                fx.CreatePop("Miss");
                return;
            }

            // 背刺判断
            if (
                (!entity.facingRight && sourceStats.transform.position.y > transform.position.y)
                || (entity.facingRight && sourceStats.transform.position.y < transform.position.y)
            )
                isBackAttack = true;
            else
                isBackAttack = false;

            float totalDamage = sourceStats.damage.Value + sourceStats.strength.Value;

            var canCrit = CanCrit(sourceStats);
            beCrit = canCrit;
            if (canCrit) totalDamage = CalculateCritDamage(totalDamage);
            

            totalDamage = CheckArmor(sourceStats, totalDamage);

            // TakeDamage(totalDamage, sourceStats);
            BeMagicalDamage(sourceStats, totalDamage);
        }

        /// <summary>
        /// 技能伤害
        /// </summary>
        /// <param name="sourceStats"></param>
        /// <param name="damage"></param>
        /// <param name="damageType"></param>
        public virtual void BeDamage(CharacterStats sourceStats, int damage, DamageType damageType)
        {
            if (CanAvoidAttack(sourceStats))
                return;

            float totalDamage = damage;
            if (CanCrit(sourceStats))
                totalDamage = CalculateCritDamage(totalDamage);

            if (damageType == DamageType.Normal)
                totalDamage = CheckArmor(sourceStats, totalDamage);
            else if (damageType == DamageType.Magic)
                totalDamage = CheckMagicArmor(sourceStats, totalDamage);

            TakeDamage(totalDamage, sourceStats);
        }

        #region  魔法普通攻击
        public virtual void BeMagicalDamage(CharacterStats sourceStats, float totalDamage)
        {
            float fireDamage = sourceStats.fireDamage.Value;
            float iceDamage = sourceStats.iceDamage.Value;
            float electricDamage = sourceStats.electricDamage.Value;

            //挂buff
            if (Mathf.Max(fireDamage, iceDamage, electricDamage) <= 0)
            {
                TakeDamage(totalDamage, sourceStats);
                return;
            }

            totalDamage =
                totalDamage + fireDamage + iceDamage + electricDamage + intelligence.Value;
            totalDamage = CheckMagicArmor(sourceStats, totalDamage);

            TakeDamage(totalDamage, sourceStats);

            var damages = new Dictionary<BuffType, float>
            {
                { BuffType.Ignited, sourceStats.fireDamage.Value },
                { BuffType.Frozen, sourceStats.iceDamage.Value },
                { BuffType.Shocked, sourceStats.electricDamage.Value }
            };

            var maxDamageType = damages.Aggregate((l, r) => l.Value > r.Value ? l : r).Key;

            switch (maxDamageType)
            {
                case BuffType.Ignited:
                    AddBuff(BuffType.Ignited);
                    break;
                case BuffType.Frozen:
                    AddBuff(BuffType.Frozen);
                    break;
                case BuffType.Shocked:
                    AddBuff(BuffType.Shocked, sourceStats);
                    break;
            }
        }
        #endregion
        #endregion



        #region buff

        public void AddBuff(BuffType buffType, CharacterStats sourceStats = null)
        {
            var buff = buffs.FirstOrDefault(b => b.buffType == buffType);
            if (buff != null)
            {
                //处理覆盖情况
                switch (buff.buffOverlap)
                {
                    case Buff.BuffOverlap.None:
                        //无视
                        break;
                    case Buff.BuffOverlap.StackedTime:
                        buff.timer = buff.interalTime;
                        break;
                    case Buff.BuffOverlap.StackedLayer:
                        buff.level++;
                        break;
                    case Buff.BuffOverlap.ResterTime:
                        RemoveBuff(buff);
                        AddBuff(buffType);
                        break;
                }
            }
            else
            {
                buff = BuffFactory.Instance.CreateBuff(buffType);
                buff.currentTarget = this;
                buff.deployStats = sourceStats;
                buffs.Add(buff);
                buff.OnStart();
            }
        }

        public void ReFreshBuff()
        {
            // 后加入先执行
            for (int i = buffs.Count - 1; i >= 0; i--)
            {
                buffs[i].OnEffect();
            }
        }

        public void RemoveBuff(BuffType buffType)
        {
            var buff = buffs.FirstOrDefault(b => b.buffType == buffType);
            if (buff != null)
            {
                RemoveBuff(buff);
            }
        }

        public void RemoveBuff(BuffBase buff)
        {
            buffs.Remove(buff);
            buff.OnEnd();
        }

        #endregion


        #region  伤害计算
        private float CheckMagicArmor(CharacterStats sourceStats, float totalDamage)
        {
            totalDamage -= magicResistance.Value + intelligence.Value * 3;
            totalDamage = Mathf.Clamp(totalDamage, 0, float.MaxValue);
            return totalDamage;
        }

        private float CheckArmor(CharacterStats sourceStats, float totalDamage)
        {
            //如果在背后，计算倍率
            if (isBackAttack)
                totalDamage -= Mathf.RoundToInt(armor.Value * backArmorMultiplier.Value);
            else
                totalDamage -= armor.Value;
            return Mathf.Clamp(totalDamage, 0, float.MaxValue);
        }

        private bool CanAvoidAttack(CharacterStats sourceStats)
        {
            var totalEvation = evasion.Value + agility.Value;
            if (totalEvation > UnityEngine.Random.Range(0, 100))
            {
                return true;
            }
            return false;
        }

        private bool CanCrit(CharacterStats sourceStats)
        {
            var totalCritChance = sourceStats.critChangce.Value + sourceStats.agility.Value;
            if (totalCritChance > UnityEngine.Random.Range(0, 100))
            {
                Debug.Log("暴击成功");
                return true;
            }
            return false;
        }

        private int CalculateCritDamage(float sourceDamage)
        {
            float totalCritPower = critPower.Value + intelligence.Value * 0.01f;
            float totalCritDamage = sourceDamage * totalCritPower;
            return Mathf.RoundToInt(totalCritDamage);
        }

        #endregion

        #region 种族判断
        public bool IsLivingBody => this.race == Race.Human;

        #endregion







        #region 死亡
        private void Die()
        {
            entity.Die();
        }
        #endregion
    }
}
